﻿/****************************************************************************************************
	Copyright (C) 2010 RapidWebDev Organization (http://rapidwebdev.org)
	Author: Eunge, Legal Name: Jian Liu, Email: eunge.liu@RapidWebDev.org

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************************************/

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using BaoJianSoft.Common;
using BaoJianSoft.Platform.Linq;
using System.Globalization;
using BaoJianSoft.Platform.Properties;
using BaoJianSoft.Common.Web;

namespace BaoJianSoft.Platform.Services
{
	/// <summary>
	/// The service to operate areas
	/// </summary>
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	public class HierarchyService : IHierarchyService
	{
		private static IHierarchyApi hierarchyApi = SpringContext.Current.GetObject<IHierarchyApi>();

		/// <summary>
		/// Find all hierarchies hit the input query on code or name.
		/// </summary>
		/// <param name="hierarchyType"></param>
		/// <param name="query"></param>
		/// <param name="maxReturnedCount"></param>
		/// <returns></returns>
		public Collection<HierarchyDataObject> FindByKeyword(string hierarchyType, string query, int maxReturnedCount)
		{
			if (string.IsNullOrEmpty(hierarchyType))
				throw new BadRequestException(Resources.InvalidHierarchyType);

			int recordCount;
			Expression<Func<HierarchyDataObject, bool>> predicate = hierarchy => (hierarchy.Code != null && hierarchy.Code.StartsWith(query, StringComparison.OrdinalIgnoreCase))
				|| (hierarchy.Name != null && hierarchy.Name.StartsWith(query, StringComparison.OrdinalIgnoreCase));

			IEnumerable<HierarchyDataObject> hierarchyDataObjects = hierarchyApi.FindHierarchyData(hierarchyType, predicate, null, "Name ASC", 0, maxReturnedCount, out recordCount);

			Collection<HierarchyDataObject> results = new Collection<HierarchyDataObject>();
			IEnumerable<HierarchyDataObject> dummyRootHierarchyDataObjects = FindHierarchyDataObjectWithParentNotExist(hierarchyDataObjects);
			foreach (HierarchyDataObject dummyRootHierarchyDataObject in dummyRootHierarchyDataObjects)
				HierarchizeHierarchyData(hierarchyDataObjects, dummyRootHierarchyDataObject, results, 0);

			return results;
		}

		private static void HierarchizeHierarchyData(IEnumerable<HierarchyDataObject> allHierarchyDataObjects, HierarchyDataObject parentHierarchyData, IList<HierarchyDataObject> results, int hierarchyLevel)
		{
			results.Add(ResolveHierarchyDisplayName(parentHierarchyData, hierarchyLevel));
			IEnumerable<HierarchyDataObject> childHierarchyDataObjects = allHierarchyDataObjects.Where(h => h.ParentHierarchyDataId == parentHierarchyData.Id);
			foreach (HierarchyDataObject childHierarchyDataObject in childHierarchyDataObjects)
				HierarchizeHierarchyData(allHierarchyDataObjects, childHierarchyDataObject, results, hierarchyLevel + 1);
		}

		private static IEnumerable<HierarchyDataObject> FindHierarchyDataObjectWithParentNotExist(IEnumerable<HierarchyDataObject> allHierarchyDataObjects)
		{
			List<HierarchyDataObject> results = new List<HierarchyDataObject>();
			foreach (HierarchyDataObject hierarchyDataObject in allHierarchyDataObjects)
			{
				if (!hierarchyDataObject.ParentHierarchyDataId.HasValue
					|| allHierarchyDataObjects.FirstOrDefault(h => h.Id == hierarchyDataObject.ParentHierarchyDataId.Value) == null)
					results.Add(hierarchyDataObject);
			}

			return results;
		}

		private static HierarchyDataObject ResolveHierarchyDisplayName(HierarchyDataObject hierarchyDataObject, int hierarchyLevel)
		{
			if (hierarchyLevel <= 0) return hierarchyDataObject;

			string prefix = "";
			for (int i = 0; i < hierarchyLevel; i++)
				prefix += "--";

			HierarchyDataObject returnValue = hierarchyDataObject.Clone();
			returnValue.Name = string.Format(CultureInfo.InvariantCulture, "{0} {1}", prefix, hierarchyDataObject.Name);
			return returnValue;
		}
	}
}
